package org.alis.rpc.common.paap;

import org.alis.rpc.common.paap.cache.bean.ConfigValue;
import org.alis.rpc.common.paap.constant.Constants;
import org.apache.commons.lang3.StringUtils;

import java.util.List;
import java.util.Map;

/**
 *
 * @author luochuan@thunisoft.com
 * @date  2020/8/28 11:15
 * @version v1.0.0
 */

public class ConfigUtils {

    private static IConfigureProvider provider;

    /**
     * 是否允许环境变量覆盖配置中心
     */
    private static final String ENV_OVERRIDE_ENABLE = "env.override.enable";

    static {
        if (Boolean.parseBoolean(System.getProperty(ENV_OVERRIDE_ENABLE))) {
            provider = new WithEnvProvider();
        } else {
            provider = new DefaultProvider();
        }
    }

    public static Configurator getSysConfigurator() {
        return AppConfigContext.getConfigurator();
    }


    public static Map<String, String> getAllSysConfig(String key) {
        Configurator configurator = getSysConfigurator();
        return configurator.getAllSysConfig(key);
    }

    /**
     * 获取某个配置信息的默认值
     *
     * @param key 配置项的key
     * @return String 配置项的值
     */
    public static String getSysConfig(String key) {
        Configurator configurator = getSysConfigurator();
        if (configurator == null) {
            return null;
        }
        String value = configurator.getSysConfig(key);
        if (value == null) {
            value = getConfigFromValAndEnv(key);
        }
        return value;
    }

    /**
     * Get specific corp value, if not exist. <code>null</code> is returned.
     *
     * @param key  configuration key.
     * @param corp corp id.
     * @return Corp config value.
     */
    public static String getSysConfigWithCorp(String key, String corp) {
        return provider.getSysConfigWithCorp(key, corp);
    }

    /**
     * 获取指定单位下的某项配置的值。如果指定单位下的配置值为空的话(null)，返回默认值。
     *
     * @param key    配置信息的key
     * @param corpId 单位标识
     * @return 单位配置项的value, 类型
     */
    public static String getSysConfig(String key, String corpId) {
        return provider.getSysConfig(key, corpId);
    }

    /**
     * 获取指定单位下的某项配置的值。
     * 如果配置项对应的值是 {@link StringUtils#EMPTY} 的话，则返回这个配置信息的默认值。
     *
     * @param key  配置 key
     * @param corp 单位标识
     * @return 配置值
     */
    public static String getSysConfigWithDefault(String key, String corp) {
        return provider.getSysConfigWithDefault(key, corp);
    }

    /**
     * 获取配置
     * 优先级:1.缓存中的配置服务配置 2.Spring聚合后的props中的配置 3.启动参数 4.环境变量
     *
     * @param key 配置 key
     * @return 配置值
     */
    public static String getLocalConfig(String key) {
        String value = getSysConfig(key);
        if (value == null) {
            value = getConfigFromValAndEnv(key);
        }
        return value;
    }

    /**
     * Get specific configuration value from system property and environment variable.
     * Note: System property have a higher priority than environment variable.
     *
     * @param key configuration key.
     * @return configuration value.
     */
    public static String getConfigFromValAndEnv(String key) {
        String value = System.getProperty(key);
        if (value == null) {
            value = System.getenv(key);
        }
        return value;
    }

    /**
     * 直接去配置服务端获取配置信息，不是在客户端缓存中取
     *
     * @param appId  应用分组id
     * @param key    配置信息的key
     * @param corpId 单位标识
     * @return
     */
    public static String getSysConfig(String appId, String key, String corpId) {
        Configurator configurator = getSysConfigurator();
        if (configurator == null) {
            return null;
        }
        return configurator.getSysConfig(appId, key, corpId);
    }


    /**
     * 获取默认值对应的 key.
     * 1. 如果在启动参数中配置了 corp. 那对应的 corp 为默认值 key.
     * 2. 启动参数中没有配置 corp. 对应的默认值 key 为 default.
     *
     * @return Default key.
     */
    public static String getDefaultKey() {
        String valueKey = getConfigFromValAndEnv(Constants.STARTUP_PARAM_CORP);
        if (valueKey == null) {
            valueKey = Constants.DEFAULT_VALUE_KEY;
        }
        return valueKey;
    }

    /**
     * @param appId 应用系统标识id
     */
    public static String addConfigValue(String appId, List<ConfigValue> configvalues) {
        Configurator configurator = getSysConfigurator();
        if (configurator == null) {
            return null;
        }
        return configurator.addConfigValue(appId, configvalues);
    }

    /**
     * 配置提供者
     */
    interface IConfigureProvider {
        /**
         * 获取指定单位下的某项配置的值。如果指定单位下的配置值为空的话(null)，返回默认值。
         *
         * @param key    配置信息的key
         * @param corpId 单位标识
         * @return 单位配置项的value, 类型
         */
        String getSysConfig(String key, String corpId);

        /**
         * Get specific corp value, if not exist. <code>null</code> is returned.
         *
         * @param key  configuration key.
         * @param corp corp id.
         * @return Corp config value.
         */
        String getSysConfigWithCorp(String key, String corp);

        /**
         * 获取指定单位下的某项配置的值。
         * 如果配置项对应的值是 {@link StringUtils#EMPTY} 的话，则返回这个配置信息的默认值。
         *
         * @param key  配置 key
         * @param corp 单位标识
         * @return 配置值
         */
        String getSysConfigWithDefault(String key, String corp);
    }


    static class DefaultProvider implements IConfigureProvider {

        @Override
        public String getSysConfig(String key, String corpId) {
            Configurator configurator = getSysConfigurator();
            if (configurator == null) {
                return null;
            }
            return configurator.getSysConfig(key, corpId);
        }

        @Override
        public String getSysConfigWithCorp(String key, String corp) {
            Configurator configurator = getSysConfigurator();
            if (configurator == null) {
                return null;
            }
            return configurator.getSysConfigWithCorp(key, corp);
        }


        @Override
        public String getSysConfigWithDefault(String key, String corp) {
            if (StringUtils.isBlank(corp)) {
                return ConfigUtils.getSysConfig(key);
            }
            String value = getSysConfigWithCorp(key, corp);
            if (StringUtils.isBlank(value)) {
                return ConfigUtils.getSysConfig(key);
            }
            return value;
        }

        static Configurator getSysConfigurator() {
            return AppConfigContext.getConfigurator();
        }
    }


    static class WithEnvProvider extends DefaultProvider {

        @Override
        public String getSysConfig(String key, String corp) {
            String property = System.getProperty(corp + "." + key);
            if (StringUtils.isNotBlank(property)) {
                return property;
            }
            return super.getSysConfig(key, corp);
        }

        @Override
        public String getSysConfigWithCorp(String key, String corp) {
            String property = System.getProperty(corp + "." + key);
            if (StringUtils.isNotBlank(property)) {
                return property;
            }
            return super.getSysConfigWithCorp(key, corp);
        }

        @Override
        public String getSysConfigWithDefault(String key, String corp) {
            String property = System.getProperty(corp + "." + key);
            if (StringUtils.isNotBlank(property)) {
                return property;
            }
            return super.getSysConfigWithDefault(key, corp);
        }

    }
}
